<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>类的基本知识</title>
    </head>
    <body>
        <script type="text/javascript">
            /**
             * 总结:
             * 1. 类中的构造方法不是必须写的，当需要进行初始化操作时才需要写。
             * 2. 如果A类继承了B类，且A类中写了构造方法，那么A类构造方法中必须要调用super。
             * 3. 类中所定义的方法，都放在了类的原型对象上，供实例使用。
             */
            // 创建一个Person类
            class Person {
                // 构造方法
                constructor(name, age) {
                    this.name = name;
                    this.age = age;
                }

                // 一般方法
                speak() {
                    // speak方法放在了Person类的原型对象上，供实例使用
                    // 通过Person实例调用speak时，this就是Person实例本身。可以使用call、apply等方法改变this指向的内容
                    console.log(`我叫${this.name}，我的年龄是${this.age}岁`);
                }
            }

            // 类的继承
            // 子类若不提供构造方法，默认使用父类的构造方法
            class Student extends Person {
                constructor(name, age, grade) {
                    // 子类构造器中必须调用super
                    super(name, age);

                    this.grade = grade;
                }

                // 重写从父类继承来的方法
                speak() {
                    console.log(
                        `我叫${this.name}，我的年龄是${this.age}岁，我在上${this.grade}`
                    );
                }

                study() {
                    console.log(`我很努力地学习`);
                }
            }

            // 创建Person的实例对象
            const p1 = new Person("tom", 18);
            const p2 = new Person("jerry", 19);

            console.log(p1);
            console.log(p2);

            p1.speak();
            p2.speak();

            // 创建Student的实例对象
            const s1 = new Student("张三", 15, "高一");
            console.log(s1);
            s1.speak();
            s1.study();

            class Car {
                constructor(name, price) {
                    this.name = name;
                    this.price = price;
                }

                // 类实例属性
                wheel = 4;
            }
            const c1 = new Car("奔驰", 1999);
            console.log(c1);
        </script>
    </body>
</html>
